
import java.util.HashMap;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Set;

public class Node implements Comparable<Node>, Serializable{

	/**
	 * 
	 */
	private static final long serialVersionUID = -2823262179696210374L;
	public String name;
	public HashMap<Character, ArrayList<Node>> adjList;
	public boolean accepting;
	private static Integer numNodes = 0;
	public String tokenName;



	public Node(){
		this(((Integer)(numNodes+1)).toString(), false); //Use a default name if we don't specify one
	}

	public Node(boolean accepting){
		this(((Integer)(numNodes+1)).toString(), accepting); //Use a default name if we don't specify one
	}

	public Node(String name){
		this(name, false);
	}

	public Node(String name, boolean accepting){
		this.name = name;
		adjList = new HashMap<Character, ArrayList<Node>>();
		this.accepting = accepting;
		numNodes++;
		//this.marked = false;
	}


	public String toString(){
		return name;
	}


	/*
	 * Given a list of values on which a node should transition to 
	 * a particular target node, we add all such transitions 
	 * to the original node's adjacency list.
	 */
	public void addTransitions(char[] inputs, Node target){
		for (int i = 0; i < inputs.length; i++){
			if (adjList.containsKey(inputs[i])){ // We already have a transition on this value
				adjList.get(inputs[i]).add(target);
			}
			else{ //We don't yet have a transition on this node=
				ArrayList<Node> temp = new ArrayList<Node>();
				temp.add(target);
				adjList.put(inputs[i], temp);
			}
		}
	}


	//Need to do another BFS, like in DFANode constructor
	public static Set<Node> epsClosure(Set<Node> nodes){

		Set<Node> ret = new HashSet<Node>();
		ArrayList<Node> queue = new ArrayList<Node>();
		HashSet<String> visited = new HashSet<String>();
		ArrayList<Node> reachable;
		queue.addAll(nodes);
		Node curnode;
		while (!queue.isEmpty()){
			curnode = queue.remove(0);
			if (visited.contains(curnode.name)){//We've already done this
				continue;
			}
			ret.add(curnode);
			visited.add(curnode.name);

			reachable = curnode.adjList.get(NFA.EPS_CHAR);
			if (reachable != null){
				for (Node n : reachable){
					if (!visited.contains(n.name)){
						queue.add(n);
					}
					ret.add(n);
				}
			}
		}

		return ret;
	}



	public static void main(String[] args){
		String toscanFn  = "minitest.txt";		
		String grammarFn = "MiniRE Tokens.txt";
		
		Lexer lex = Lexer.getLexer(grammarFn);//try to load it, and make it otherwise
		
		if (args != null && args.length != 0){//if you specify an argument, we don't save it
			lex.dfa.save(grammarFn);
		}
		ArrayList<ArrayList<String>> tokens = lex.scanFile(toscanFn);
		System.out.println("I found the following tokens:\n" + tokens);
	}

	@Override
	public int compareTo(Node o) {
		return name.compareTo(o.name);
	}

}


















